package logic.impl;

import java.io.File;
import java.io.FileInputStream;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;

import model.AddressWrapper;
import model.VCardWrapper;

/**
 * 
 * resolver:
 * 
 * - if region of address field is missing, try to resolve it using the postal code
 *
 */
public class ResolverRegionFromPostalCode extends LogicElementBaseClass {
	
	class CountryPostalCodeInfo {
		public boolean patternAsRegex;
		public Properties mapping;
	}
	
	private Hashtable<String, CountryPostalCodeInfo>countryMappings;
	
	@Override
	public void init(Properties resolverProperties) {
		super.init(resolverProperties);
		
		countryMappings = new Hashtable<String, CountryPostalCodeInfo>();
		
		/**
		 * load country mappings
		 */
		if(resolverProperties.containsKey("ResolverRegionFromPostalCode.PathMappings")) {
			try {
				String pathDir = resolverProperties.getProperty("ResolverRegionFromPostalCode.PathMappings");
				log.info("loading postalCode mappings from:" + pathDir);
								
				File dir = new File(pathDir);
				File[] mappingList = dir.listFiles();
				
				/**
				 * search given directory for mapping files
				 */
				if(mappingList != null) {
					for(int i = 0; i < mappingList.length; i++) {
						File myMappingFile = mappingList[i];
						if(myMappingFile.isDirectory() || myMappingFile.canRead() == false) continue;
						
						Properties props = new Properties();
						props.load(new FileInputStream(myMappingFile));
						
						String countryName = props.getProperty("countryName");
						log.info("loading postalCode-Region mapping file for country: " + countryName +
								" from: " + myMappingFile.getAbsolutePath());
						
						CountryPostalCodeInfo cMapping = new CountryPostalCodeInfo();
						cMapping.patternAsRegex = new Boolean(
								props.getProperty("patternAsRegex"))
							.booleanValue();
	
						props.remove("countryName");
						props.remove("patternAsRegex");
						
						cMapping.mapping = props;
						
						countryMappings.put(countryName, cMapping);
						
					}
				}
			} catch (Exception exc) {
				log.error(exc);
				exc.printStackTrace();
			}
		}
		
		
	}

	public void performResolving() {

		Vector <VCardWrapper>addressCards = this.getAddressBook().getAddressCards();
		for(int i = 0; i < addressCards.size(); i++) {
			VCardWrapper myCard = addressCards.get(i);
			
			if(myCard.existsAddress()) {
							
				AddressWrapper address = myCard.getAddress();

				if(address.existsCountryName() &&
						address.existsRegion() == false &&
						address.existsPostalCode()) {
					/**
					 * try to resolve region from postal code
					 */
					performResolvingRegionFromPostalCode(address);
					
				}
				
			}
		}

		
	}	
	
	public void performResolvingRegionFromPostalCode(AddressWrapper address) {
				
		if(this.countryMappings.containsKey(address.getCountryName())) {
			CountryPostalCodeInfo countryMapping = this.countryMappings.get(address.getCountryName());
			
			/**
			 * region can be resolved by exact postalCode match
			 */
			if(countryMapping.patternAsRegex == false) {
				String resolvedRegion = countryMapping.mapping.getProperty(address.getPostalCode());
				address.setRegion(resolvedRegion);
				log.info("++++++++++ resolved region " + resolvedRegion + " from countryCode: " + 
						address.getPostalCode() + " for country: " + address.getCountryName() + " ++++++++++");
			} else {
				/**
				 * postalCode within mapping is given as regex
				 */
				Iterator keyIter = countryMapping.mapping.keySet().iterator();
				while(keyIter.hasNext()) {
					String key = (String) keyIter.next();
					
					if(address.getPostalCode().
							matches(key)) {
						String resolvedRegion = countryMapping.mapping.getProperty(key);
						address.setRegion(resolvedRegion);
						log.info("++++++++++ resolved region " + resolvedRegion + " from countryCode: " + 
								address.getPostalCode() + " for country: " + address.getCountryName() + " ++++++++++");
						return;
					}
				}
			}
		}
	}
	
	
}